import { getMockData } from "@/api";
import { TableObject, FieldObject, CodeObject } from "@/type/global";
import { formatToHump, formatToLine } from "./utils";
import { proTableOption } from ".";
const dataLen = 10;
export async function generateCode(options: TableObject): Promise<CodeObject> {
    return {
        ts: gererateTS(options),
        java: generateJAVA(options),
        sql: await generateSQL(options),
        json: await generateJSON(options.fieldList!),
        proTable: generateProTableCode(options),
        proForm: generateProFormCode(options)
    }
}

async function generateJSON(fields: FieldObject[]): Promise<string> {

    let str = ``;
    for (let i = 0; i < dataLen; i++) {
        str += await generateInnerJSON(fields, i)
    }
    str = `
[
    ${str}
]`
    return str;
}

async function generateInnerJSON(fields: FieldObject[], index: number) {
    let str = ``;
    const len = fields.length;

    for (let i = 0; i < len; i++) {
        const item = fields[i];
        const result = await defaultValueUtils(item);
        str += `    "${item.fieldName}": "${result}"${i === fields.length - 1 ? '' : ',\r\n\t'}`
    }

    str = `${index == 0 ? '' : '\t'}{
    ${str}
    }${index == dataLen - 1 ? '' : ',\r'}
`
    return str;
}

// 生成 ts 代码部分
function gererateTS(options: TableObject): string {

    let str = `/*
* @description ${options.tableComment || '描述'}
*/
interface ${formatToHump(options.tableName, true)} {
    ${getKeyTypeOfTS(options.fieldList!)}
} `;
    return str;
}

/**
 * 字段数组转类型和变量名 -- ts
 */
function getKeyTypeOfTS(list: FieldObject[]) {
    let str = ``;
    list.forEach((item, index) => {
        str += `${index == 0 ? '' : '\t'}${formatToHump(item.fieldName)}${!item.isNull ? '?' : ''}: ${parseType(item).ts} ${item.comment ? '//' + item.comment : ''} \r`
    })

    return str;
}

function parseType(obj: FieldObject): { ts: string, java: string } {
    if (!obj.fieldType) {
        return { ts: 'string', java: 'String' };
    }
    if (['varchar', 'blob', 'longblob', 'longtext', 'json'].includes(obj.fieldType)) {
        return { ts: 'string', java: 'String' };
    } else if (['int', 'bigint', 'float', 'double'].includes(obj.fieldType)) {
        return { ts: 'number', java: 'Integer' };
    } else if (obj.fieldType == 'tinyint') {
        return { ts: 'boolean', java: 'Boolean' };
    } else if (obj.fieldType == 'datetime') {
        return { ts: 'Date', java: 'Date' };
    } else {
        return { ts: 'string', java: 'String' };
    }
}

// 生成 Java 代码
function generateJAVA(options: TableObject): string {
    let str = `import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import lombok.Data;
// ${options.tableComment || '描述'}
@Data
${hasMyOption(options.fieldList!, 'mybatis') ? '@TableName("' + options.tableName + '")' : ''}
${hasMyOption(options.fieldList!, 'swagger') ? '@ApiModel("' + (options.tableComment || "表名") + '")' : ''}
public class ${formatToHump(options.tableName, true)} {
    ${getKeyTypeOfJava(options.fieldList!)}
}`;
    return str;
}

function hasMyOption(options: FieldObject[], option: string) {
    const resultList: boolean[] = [];
    options.forEach(item => {
        if (item.javaOptions) {
            resultList.push(item.javaOptions.includes(option));
        }
    })
    return resultList.some(item => item === true);
}

function getKeyTypeOfJava(list: FieldObject[]) {
    let str = ``;
    list.forEach((item) => {
        str += `
        ${item.javaOptions?.includes('mybatis') ? item.options?.includes('primaryKey') ? '@TableId(type = IdType.ASSIGN_ID, value = "' + item.fieldName + '")' : '@TableField("' + item.fieldName + '")' : ''}
        ${item.javaOptions?.includes('swagger') ? '@ApiModelProperty("' + (item.comment || item.fieldName) + '")' : ''}
        private ${parseType(item).java} ${formatToHump(item.fieldName)}; ${item.comment ? '//' + item.comment : ''} \r\n\t
`
    })
    return str;
}

// SQL 代码
async function generateSQL(options: TableObject): Promise<{ create: string, insert: string, index: string }> {
    const createNameList = options.tableName.split(',').map(item => item.replaceAll('-', ''));
    const commentList = options.tableComment?.split(',');
    let create: string = '';
    createNameList.forEach((tName, i) => {
        create += `create table ${tName.toLowerCase()} (${generateCreateSQL(options.fieldList!)}) ${(commentList && commentList.length) ? "comment '" + (commentList![i] || '表描述') + "'" : ''} ;
`
    })
    return { create, insert: await generateInsertCode(options), index: gernerteIndexSQL(options) };
}

function gernerteIndexSQL(options: TableObject) {
    const { fieldList, tableName } = options;
    const tableNameList = tableName.split(',').map(item => item.replaceAll('-', '').toLowerCase());
    let sql = '';
    tableNameList.forEach(tName => {
        fieldList?.forEach(item => {
            if (item.index) {
                sql += `CREATE INDEX ${item.indexName!} ON ${tName}(${item.fieldName});
`
            }
        })
    })
    return sql;
}

function generateCreateSQL(fields: FieldObject[]) {
    let str = ``;
    fields.forEach((item, index) => {
        str += `${item.fieldName} ${[void 0, 'varchar'].includes(item.fieldType) ? 'varchar(255)' : item.fieldType} ${item.autoIncrement ? 'auto_increment' : ''} ${item.isNull ? 'not null' : ''} ${item.defaultValue ? "default '" + item.defaultValue + "'" : ""} comment '${item.comment}' ${index === fields.length - 1 ? '' : ','}`
    });
    return str + generatePrimaryKeyCode(fields);
}

// 生成主键代码
function generatePrimaryKeyCode(fields: FieldObject[]) {
    let str = ``;
    const primaryKeyList = fields.filter(item => item.primaryKey);
    if (!primaryKeyList.length) return str;
    str = `, primary key(${primaryKeyList.map(item => item.fieldName).join(',')})`;
    return str;
}

// 生成插入语句的代码
async function generateInsertCode(table: TableObject) {
    const { tableName } = table;
    const tableNameList = tableName.split(',');
    let sql: string = ``;
    for (let t = 0; t < tableNameList.length; t++) {
        const tName = tableNameList[t];
        for (let i = 0; i < dataLen; i++) {
            sql += `insert into ${tName} ${await generatePreInserCode(table.fieldList!)} \r\n`;
        }
    }
    return sql;
}

async function generatePreInserCode(fieldList: FieldObject[]) {
    const len = fieldList.length;
    const values: string[] = [];
    for (let i = 0; i < len; i++) {
        const item = fieldList[i];
        const value = await defaultValueUtils(item);
        values[i] = `'${value}'`;
    }

    let sql = `(${fieldList.map(item => item.fieldName).join(',')}) values(${values.join(',')}); `;
    return sql;
}

async function defaultValueUtils(field: FieldObject): Promise<string> {
    try {
        if (field.defaultValue) return field.defaultValue;
        if (!field.mockType) return '';
        let result: any = ''
        if (localStorage.getItem(field.mockType)) {
            result = JSON.parse(localStorage.getItem(field.mockType)!)
        } else {
            result = await getMockData(field.mockType);
            localStorage.setItem(field.mockType, JSON.stringify(result))
        }
        let value = result[0].data[Math.floor(Math.random() * result[0].data.length)];
        return value;
    } catch (err) {
        return '';
    }
}

// 生成 ProTable 代码
function generateProTableCode(table: TableObject) {
    let str = `[
        ${createProTableItem(table.fieldList!)}
    ]`
    return str;
}

function createProTableItem(filed: FieldObject[]) {
    let value = ``;
    filed.forEach(item => {
        value += `
        {
            key: ${`'${formatToHump(item.fieldName)}'`},
            title: ${`'${item.comment || ''}'` || "''"},
            type: ${`'${item.proTableSearchOption || 'input'}'`},
            hideInSearch: ${item.proTableOptions ? item.proTableOptions.includes('hideInSearch') : false},
            hideInTable: ${item.proTableOptions ? item.proTableOptions.includes('hideInTable') : false},
            isSlot: ${item.proTableOptions ? item.proTableOptions.includes('isSlot') : false},
            isFormSlot: ${item.proTableOptions ? item.proTableOptions.includes('isFormSlot') : false},
        },\r\n
        `
    })

    return value;
}

// 生成 ProForm 代码
function generateProFormCode(table: TableObject) {
    let str = `[
        ${createProFormItem(table.fieldList!)}
    ]`
    return str;
}

function createProFormItem(filed: FieldObject[]) {
    let value = ``;
    filed.forEach(item => {
        value += `
        {
            name: ${`'${formatToHump(item.fieldName)}'`},
            label: ${`'${item.comment || ''}'`},
            type: ${`'${item.proFormTypeOption || 'input'}'`},
            hideInForm: ${item.proTableOptions ? item.proTableOptions.includes('hideInForm') : false},
            disabled: ${item.proTableOptions ? item.proTableOptions.includes('disabled') : false},
            readonly: ${item.proTableOptions ? item.proTableOptions.includes('readonly') : false},
        },\r\n
        `
    })

    return value;
}
